/****************************************************************************
 * Copyright (C) 2009-2010 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#ifndef __molecule_aromatic_cycles_extractor_h__
#define __molecule_aromatic_cycles_extractor_h__

#include "base_cpp/array.h"
#include "base_cpp/tlscont.h"
#include "base_cpp/exception.h"

class Molecule;
class Graph;

// This class used to get for bond all possible 
// aromatic cycles containing such bond.
// All internal information are collected only on demand.
class MoleculeAromaticCyclesExtractor
{
public:
   MoleculeAromaticCyclesExtractor (const Molecule &mol);

   // Return possible aromatic cycles indices containing bond specified
   void extractBondAromaticCycles (int bond, Array<int> &cycles_indices, 
      int max_cycle_length = -1);

   // Get specific cycle length, vertices and edges
   int getCycleLength (int cycle_idx) const;
   const int* getCycleVertices (int idx) const;
   const int* getCycleEdges    (int idx) const;

   DEF_ERROR("aromatic cycles extractor");
private:
   void _collectCycles  (int bond, int max_cycle_length);
   bool _hasCycleBond   (int cycle_idx, int bond) const;

   void _extractAromaticSystem (int bond, Array<int> &vertices, Array<int> &edges) const;
   void _extractPiLables       (const Array<int> &vertices, Array<int> &pi_labels) const;

   static bool _handleCycle(const Graph &graph, const Array<int> &vertices, 
                     const Array<int> &edges, void *context);

   struct AromaticGroup
   {
      int start_cycles;
      int end_cycles;
      int max_cycle_length;
   };

   struct EnumerationContext
   {
      MoleculeAromaticCyclesExtractor *self;
      Array<int> aromatic_vertices;
      Array<int> aromatic_edges;
      Array<int> pi_labels;
   };

   const Molecule &_mol;
   TL_CP_DECL(Array<int>, _cycles_vertices);
   TL_CP_DECL(Array<int>, _cycles_edges);
   TL_CP_DECL(Array<int>, _cycles_offset);
   TL_CP_DECL(Array<AromaticGroup>, _aromatic_groups);
   TL_CP_DECL(Array<int>, _bond_aromatic_group);
};

#endif // __molecule_aromatic_cycles_extractor_h__
